//+-------------------------------------------------------------------------------+
//| Copyright (c) 2003 Liping Dai. All rights reserved.                           |
//| Web: www.lipingshare.com                                                      |
//| Email: lipingshare@yahoo.com                                                  |
//|                                                                               |
//| Copyright and Permission Details:                                             |
//| =================================                                             |
//| Permission is hereby granted, free of charge, to any person obtaining a copy  |
//| of this software and associated documentation files (the "Software"), to deal |
//| in the Software without restriction, including without limitation the rights  |
//| to use, copy, modify, merge, publish, distribute, and/or sell copies of the   |
//| Software, subject to the following conditions:                                |
//|                                                                               |
//| 1. Redistributions of source code must retain the above copyright notice, this|
//| list of conditions and the following disclaimer.                              |
//|                                                                               |
//| 2. Redistributions in binary form must reproduce the above copyright notice,  |
//| this list of conditions and the following disclaimer in the documentation     |
//| and/or other materials provided with the distribution.                        |
//|                                                                               |
//| THE SOFTWARE PRODUCT IS PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND,        |
//| EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED         |
//| WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR        |
//| A PARTICULAR PURPOSE.                                                         |
//+-------------------------------------------------------------------------------+

using System.IO;

namespace LipingShare.LCLib.Asn1Processor
{
    /// <summary>
    /// IAsn1Node interface.
    /// </summary>
    internal interface IAsn1Node
    {
        /// <summary>
        /// Load data from Stream.
        /// </summary>
        /// <param name="xdata"></param>
        /// <returns>true:Succeed; false:failed.</returns>
        bool LoadData(Stream xdata);

        /// <summary>
        /// Save node data into Stream.
        /// </summary>
        /// <param name="xdata">Stream.</param>
        /// <returns>true:Succeed; false:failed.</returns>
        bool SaveData(Stream xdata);

        /// <summary>
        /// Get parent node.
        /// </summary>
        Asn1Node ParentNode { get; }

        /// <summary>
        /// Add child node at the end of children list.
        /// </summary>
        /// <param name="xdata">Asn1Node</param>
        void AddChild(Asn1Node xdata);

        /// <summary>
        /// Insert a node in the children list before the pointed index.
        /// </summary>
        /// <param name="xdata">Asn1Node</param>
        /// <param name="index">0 based index.</param>
        int InsertChild(Asn1Node xdata, int index);

        /// <summary>
        /// Insert a node in the children list before the pointed node.
        /// </summary>
        /// <param name="xdata">Asn1Node that will be instered in the children list.</param>
        /// <param name="indexNode">Index node.</param>
        /// <returns>New node index.</returns>
        int InsertChild(Asn1Node xdata, Asn1Node indexNode);

        /// <summary>
        /// Insert a node in the children list after the pointed index.
        /// </summary>
        /// <param name="xdata">Asn1Node</param>
        /// <param name="index">0 based index.</param>
        /// <returns>New node index.</returns>
        int InsertChildAfter(Asn1Node xdata, int index);

        /// <summary>
        /// Insert a node in the children list after the pointed node.
        /// </summary>
        /// <param name="xdata">Asn1Node that will be instered in the children list.</param>
        /// <param name="indexNode">Index node.</param>
        /// <returns>New node index.</returns>
        int InsertChildAfter(Asn1Node xdata, Asn1Node indexNode);

        /// <summary>
        /// Remove a child from children node list by index.
        /// </summary>
        /// <param name="index">0 based index.</param>
        /// <returns>The Asn1Node just removed from the list.</returns>
        Asn1Node RemoveChild(int index);

        /// <summary>
        /// Remove the child from children node list.
        /// </summary>
        /// <param name="node">The node needs to be removed.</param>
        /// <returns></returns>
        Asn1Node RemoveChild(Asn1Node node);

        /// <summary>
        /// Get child node count.
        /// </summary>
        long ChildNodeCount { get; }

        /// <summary>
        /// Retrieve child node by index.
        /// </summary>
        /// <param name="index">0 based index.</param>
        /// <returns>0 based index.</returns>
        Asn1Node GetChildNode(int index);

        /// <summary>
        /// Get descendant node by node path.
        /// </summary>
        /// <param name="nodePath">relative node path that refer to current node.</param>
        /// <returns></returns>
        Asn1Node GetDescendantNodeByPath(string nodePath);

        /// <summary>
        /// Get/Set tag value.
        /// </summary>
        byte Tag { get; set; }

        byte MaskedTag { get; }

        /// <summary>
        /// Get tag name.
        /// </summary>
        string TagName { get; }

        /// <summary>
        /// Get data length. Not included the unused bits byte for BITSTRING.
        /// </summary>
        long DataLength { get; }

        /// <summary>
        /// Get the length field bytes.
        /// </summary>
        long LengthFieldBytes { get; }

        /// <summary>
        /// Get data offset.
        /// </summary>
        long DataOffset { get; }

        /// <summary>
        /// Get unused bits for BITSTRING.
        /// </summary>
        byte UnusedBits { get; }

        /// <summary>
        /// Get/Set node data by byte[], the data length field content and all the
        /// node in the parent chain will be adjusted.
        /// </summary>
        byte[] Data { get; set; }

        /// <summary>
        /// Get/Set parseEncapsulatedData. This property will be inherited by the
        /// child nodes when loading data.
        /// </summary>
        bool ParseEncapsulatedData { get; set; }

        /// <summary>
        /// Get the deepness of the node.
        /// </summary>
        long Deepness { get; }

        /// <summary>
        /// Get the path string of the node.
        /// </summary>
        string Path { get; }

        /// <summary>
        /// Get the node and all the descendents text description.
        /// </summary>
        /// <param name="startNode">starting node.</param>
        /// <param name="lineLen">line length.</param>
        /// <returns></returns>
        string GetText(Asn1Node startNode, int lineLen);

        /// <summary>
        /// Retrieve the node description.
        /// </summary>
        /// <param name="pureHexMode">true:Return hex string only;
        /// false:Convert to more readable string depending on the node tag.</param>
        /// <returns>string</returns>
        string GetDataStr(bool pureHexMode);

        /// <summary>
        /// Get node label string.
        /// </summary>
        /// <param name="mask">
        /// <code>
        /// SHOW_OFFSET
        /// SHOW_DATA
        /// USE_HEX_OFFSET
        /// SHOW_TAG_NUMBER
        /// SHOW_PATH</code>
        /// </param>
        /// <returns>string</returns>
        string GetLabel(uint mask);

        /// <summary>
        /// Clone a new Asn1Node by current node.
        /// </summary>
        /// <returns>new node.</returns>
        Asn1Node Clone();

        /// <summary>
        /// Clear data and children list.
        /// </summary>
        void ClearAll();
    }
}
